home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Practical Algorithms for Image Analysis
/
Practical Algorithms for Image Analysis.iso
/
CH_5.7
/
XSGLL
/
XSGLL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-11
|
27KB
|
936 lines
/*
* xsgll.c
*
* Practical Algorithms for Image Analysis
*
* Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
*/
/*
* XSGLL
*
* construct segm adj lists (SAL) and segm group lists (SGL)
* by invoking manipulation routines for doubly linked lists;
* the data item associated with a particular link (node) of a list
* is defined as struct itemtype (here: Segmtype, see below);
*
* one SAL, SAL<i>, is constructed (in the form of a doubly linked
* list) for each segment <i> in the image, obtained from a Wall-Damielsson
* linear approximation and stored in a file of type .seg, and entered
* into an array sall[] of SALs;
* for convenience of subsequent construction of SGLs, each SAL
* contains segments in the order of decreasing inverse overlap, pji;
* the reference element <i> (whose pji is set to 999.0) is placed at
* the top; by setting an approriate switch (in sall.c), SALs may also be
* constructed in the order of increasing dij, (with dij for the
* reference segment set to 0.0); in that case, each list represents
* the (forward and backward) segm adjacency list of segment <i>;
*
* the segm group list is constructed by contration of SALs
* and ordered according to dij:
* segments j for which dij < 0 will be precede i in the list (b-SAL)
* segments j for which dij > 0 will be follow i in the list (f-SAL)
*
* note:
* -->short int and int are assumed to be identical (16 bits)!!
*
* -->improvements are possible to substantially reduce the amount
* of dynamically allocated memory required for SAL and SGL storage:
* in multiple copies of each segment entered in SALs, keep only
* the segment index, e.g. <j>, and the pertinent mutual parameters
* referring to the reference segment <i>, i.e., dij, pij, pji;
* this reduces the amount of memory required per list node from
* currently 12+32 bytes to 12+14 bytes;
* initialize only non-empty SGLs of which there are only n_sgl<<n_segm;
*
* note:
* to reduce amount of dynamically allocated memory in the way indicated
* in the note above, the present version of xsgll and associated modules
* maintain two segment structures (defined in sgl.h):
* the first ( struct Segm ) contains data relating to only a single segment
* (endpoints, slope, segm. index and line index), while the second structure
* ( struct Segmtype ) serves to store information relating to pairs of
* segments, relevant to SAL and SGL construction
* (pij, pji, dij, segm. index, sgl_level, SalStat);
*
* the original and conceptually preferable version of the code maintains only
* one structure referring to segments;
* see: lsgl.h, lxsgll.c,
* lsgll.c, lsall.c, ltestsegm.c, lsgl_to_poly.c,lsgl_stats.c
*
*/
#include "xsgll.h"
#define MS_TESTSET 13 /* select one of two test sets */
#define LRM_TESTSET 11 /* contained in testsegm.seg */
#define TOTAL_SEG LRM_TESTSET
#undef DEBUG
#undef DBG_MEM
#undef ECHO_INPUT
#undef SHOW_VERT
#undef SAVE_VERT /* save cluster vertex coordinates */
/* default values for thresholds used for SAL and SGL construction */
/*
* segment pairs are processed (in sall.c) if their relative orientation
* differs by less than ANGL_THRESH, their overlap pij exceeds OVLP_THRESH
* and their perpendicular distance (see sall.c, prlpar.c) does not
* exceed D_MAX
*/
#define ANGL_THRESH 10.0 /* threshold in degrees */
/* tg(th2-th1) is comp. to */
/* slp_thresh = tg(ANGL_THRESH) */
#define OVLP_THRESH 50.0 /* normalized to vary between 0.0 amd 100.0 */
#define D_MAX 50.0 /* in pixels */
#define N_BINS 10 /* number of bins in cluster area histogram */
#define NO_DISPLAY -1
#define TERSE 0
#define VERBOSE 1
#define NA_MAX 128 /* max no allowed vertices in ph.c */
/*
* global variables
*/
int loop_switch = 1; /* enable/disable loop over poly approx */
int hull_switch = 1; /* enable/disable evaluation of hull eval */
int n_ap_max = NA_MAX;
extern char *optarg;
extern int optind, opterr;
int DRAW_MODE = 1; /* 1: overwrite existing image */
/* 3: XOR, i. e. overlay output onto img */
int WRITE_FILE = 0;
int DISP_MODE = NO_DISPLAY; /* VERBOSE, TERSE or NO_DISPLAY */
int TEST_INPUT = 0;
int INPUT = 1;
int COLOR_CODE = 0; /* when set, segm clusters are color coded */
/* acc to segm normal dirn (gpoly_hull.c) */
int DISPL_CONV_HULL = 1; /* when set, display convex hull */
int MERGE = 1; /* when set, merge segments after SGL construction */
/*
* initialize list parameters
*
* note: matching function is set by call to llsetmatch() in code as needed
*/
void
init_sall (struct linklist *segm_adj_list)
{
llzero (segm_adj_list); /* init empty list */
llsetsize (sizeof (struct Segmtype), segm_adj_list);
}
/*
* initialize list parameters
*
* note: matching function is set by call to llsetmatch() in code as needed
*/
void
init_sgll (struct linklist *segm_group_list)
{
llzero (segm_group_list); /* init empty list */
llsetsize (sizeof (struct Segmtype), segm_group_list);
}
/*
* deallocate memory occupied by links in a list
*/
int
rm_llistlink (struct linklist *list)
{
int link_count;
link_count = 0;
llhead (list);
do {
lldelete (list);
link_count++;
} while (list->listlength != 0);
return (link_count);
}
/*
* display list (terse version)
*/
void
tshow_segm_list (struct linklist *list, int index)
{
struct Segmtype *segm;
int isegm = 0;
printf ("\n...list<%d>\n", index);
llhead (list);
if (ll_length (list) != 0) { /* list not empty */
do {
segm = (struct Segmtype *) list->clp->item;
printf (" %3d", segm->segm_ind);
if ((isegm + 1) % 12 == 0) {
isegm = 0;
printf ("\n");
}
} while (llnext (list) == True);
}
else
printf (" list empty\n");
}
/*
* display list
*/
void
show_segm_list (struct linklist *list, int index)
{
struct Segmtype *segm;
printf ("\n...list <%d>\n", index);
llhead (list);
if (ll_length (list) != 0) { /* list not empty */
do {
segm = (struct Segmtype *) list->clp->item;
printf (" segm: %3d", segm->segm_ind);
printf (" d(%2d,%2d): %6.2f",
index, segm->segm_ind, segm->dij);
printf ("\tp(%2d,%2d): %6.2f",
index, segm->segm_ind, segm->pij);
printf (" p(%2d,%2d): %6.2f",
segm->segm_ind, index, segm->pji);
printf (" SGL lev: %d", segm->sgl_level);
printf ("\n");
} while (llnext (list) == True);
}
else
printf (" list empty\n");
}
/*
* evaluate slope of linear segment
*/
float
fslope (struct spoint pt1, struct spoint pt2)
{
double m;
double max_slope = 500.0; /* max. poss. slope */
int x1, y1, x2, y2;
x1 = (int) pt1.x;
y1 = (int) pt1.y;
x2 = (int) pt2.x;
y2 = (int) pt2.y;
if ((int) (x2 - x1) == 0) {
if ((int) (y2 - y1) == 0)
m = 0.0;
else
m = max_slope;
}
else
m = ((double) (y2 - y1)) / ((double) (x2 - x1));
return ((float) m);
}
/*
* read first line in data file to determine size of record
*/
void
get_record_size (FILE * file, int *n_segm, int *xmax, int *ymax)
{
int retval;
if (((retval = fscanf (file, "%d %d %d", n_segm, xmax, ymax)) != 3) || (retval == EOF)) {
printf ("wrong input file format!\n");
exit (1);
}
}
/*
* read segment data from formatted data file (generally of type .seg)
* written by pcctoseg.c; first column contains segment index.
*/
void
init_segm (FILE * fp, int n_segm, struct Segm *segm)
{
int i;
int retval;
float skip_slope;
for (i = 0; i < n_segm; i++) {
retval = fscanf (fp, "%4d %3d %3d %3d %3d %f %3d",
&((segm + i)->segm_ind),
&((segm + i)->ptO.x), &((segm + i)->ptO.y),
&((segm + i)->ptF.x), &((segm + i)->ptF.y),
&skip_slope, &((segm + i)->line_ind));
/*
* recompute slope with function internal to this module
*/
(segm + i)->slope = (float) slope (&(segm + i)->ptO, &(segm + i)->ptF);
}
}
/*
* gprintf() functions:
* write to std output and, if option WRITE_FILE set, to file wbuf (stream)
*/
void
gprintf (FILE * fpOut, char *fmt,...)
{
va_list arg_ptr;
va_start (arg_ptr, fmt);
vprintf (fmt, arg_ptr);
if (WRITE_FILE == 1)
vfprintf (fpOut, fmt, arg_ptr);
va_end (arg_ptr);
}
/*
* error message
*/
void
exitmess (char *prompt, int status)
{
printf (prompt);
printf ("\n");
exit (status);
}
/*
* usage of routine
*/
void
usage (char *progname)
{
progname = last_bs (progname);
printf ("USAGE: %s infile outimg [-t] [-w] [-a ang_thresh][-p ovlp_thresh]\n", progname);
printf (" [-d d_max] [-m] [-o] [-c] [-h] [-L]\n");
printf ("\n%s constructs segm adj lists (SAL) and segment group lists (SGL)\n", progname);
printf ("given an input file containing line segment data; writes output\n");
printf ("data into file and creates image containing line segment clusters\n\n");
printf ("ARGUMENTS:\n");
printf (" infile: input filename (.seg) (ASCII)\n");
printf (" outimg: output image filename (TIF)\n\n");
printf ("OPTIONS:\n");
printf (" -t: employ test data in test_segm.c\n");
printf (" -w: write sgl parameters and stats to file fn.sgl\n");
printf ("-a angl_thresh: set angle threshold - default: 10 deg\n");
printf ("-p ovlp_thresh: set ovlp_thresh (0 <= pij <= 100) - default: 50\n");
printf (" -d d_max: set maximum dist between segments - default: 50 pixels\n");
printf (" -m: do not merge segments after SGL constr\n");
printf (" -o: overlay topological features onto image\n");
printf (" -c: display segment clusters\n");
printf (" -h: do not display conv hull, only orig. polygon\n");
printf (" -L: print Software License for this module\n");
exit (1);
}
void
main (int argc, char *argv[])
{
FILE *file, *fpOut;
static char *buf =
{"inpsegm.seg"}; /* default input file name */
static char *wsuffix =
{".sgl"}; /* suffix for output file name */
static char wbuf[13];
int ich, is;
/* threshold variables */
int i_arg;
float angl_thresh = (float) ANGL_THRESH;
float ovlp_thresh = (float) OVLP_THRESH;
float d_max = (float) D_MAX;
/* SAL */
struct linklist *sall; /* array of segm adj lists */
#ifdef DEBUG
struct linklist *csall; /* ptr to current SAL */
#endif
struct Segm *inSegm; /* sample input */
int n_segm;
int n_sall = 0;
int i;
/* SGL */
struct linklist *sgll; /* array of segm group lists */
struct linklist *csgll; /* ptr to current SGL */
int n_sgl = 0;
int rm_link;
/* vertices and convex hull */
struct spoint *poly_vert, *v_ap; /* ptr to (cycl) poly */
int *x_vert, *y_vert;
int iv, nv, nvpp;
long lnv;
struct spoint *hullctr;
int xhullc, yhullc;
double av_dirn = (double) 0.0; /* average directn of SGL segm */
float s_nem, *clust_dirn;
float maxlen, maxwidth;
float *asp_ratio; /* eccentricity of SGL */
int *ex_hist;
float min_asp_ratio, max_asp_ratio, ex_bin_width;
int min_cluster_area, max_cluster_area, area_bin_width;
int ibin, tot_number;
int *clust_area, *area_hist;
int *hull_area;
int *clust_lsz, *lsz_hist;
int min_lsz, max_lsz, nlsz_bins;
struct Bdy bd, *bdp = &bd; /* hsbaird's boundary struct */
double tot_phi = (double) -8.0;
/* graphics */
Image *ip;
int xmax = 0;
int ymax = 0;
/*
* cmd line options ( see usage() ):
*/
static char *optstring = "twa:p:d:mochL";
/*
* parse command line
*/
optind = 3;
opterr = 1; /* give error messages */
if (argc < 3)
usage (argv[0]);
while ((i_arg = getopt (argc, argv, optstring)) != EOF) {
switch (i_arg) {
case 't':
printf ("\n...option %c: ", i_arg);
printf ("employ test data in test_segm.c\n");
n_segm = TOTAL_SEG;
TEST_INPUT = 1;
INPUT = 0;
break;
case 'w':
printf ("\n...option %c: ", i_arg);
WRITE_FILE = 1;
break;
case 'a':
printf ("\n...option %c: ", i_arg);
printf ("set angle threshold to: %f\n",
angl_thresh = (float) atof (optarg));
break;
case 'p':
printf ("\n...option %c: ", i_arg);
printf ("set overlap threshold to: %f\n",
ovlp_thresh = (float) atof (optarg));
break;
case 'd':
printf ("\n...option %c: ", i_arg);
printf ("set max segm-to-segm dist to: %f\n",
d_max = (float) atof (optarg));
break;
case 'm':
printf ("\n...option %c:", i_arg);
printf (" do not merge segments after SGL construction\n");
MERGE = 0;
break;
case 'o':
printf ("\n...option %c:", i_arg);
printf (" overlay output on img in buf 1\n");
DRAW_MODE = 3;
break;
case 'c':
printf ("\n...option %c:", i_arg);
printf (" display segment clusters\n");
COLOR_CODE = 1;
break;
case 'h':
printf ("\n...option %c:", i_arg);
printf (" do not display convex hull, only original polygon\n");
DISPL_CONV_HULL = 0;
break;
case 'L':
print_sos_lic ();
exit (0);
default:
printf ("\n...unknown condition encountered\n");
exit (1);
break;
}
}
if (!TEST_INPUT) {
printf ("read segment data from file %s\n", buf = argv[1]);
/* get size of data set from file */
if ((file = fopen (buf, "r")) == NULL) {
printf ("\n...could not open file %s\n", buf);
exit (1);
}
/* initialize size variables */
get_record_size (file, &n_segm, &xmax, &ymax);
if (n_segm > MAX_REC_SIZE) {
printf ("\n...record size of %d exceeds limit of %d\n", n_segm, MAX_REC_SIZE);
exit (1);
}
/* construct output file name */
ich = 0;
while ((*(wbuf + ich) = *(buf + ich)) != '.')
ich++;
for (is = 0; is < 4; is++)
*(wbuf + (ich) + is) = *(wsuffix + is);
if (WRITE_FILE) {
if ((fpOut = fopen (wbuf, "w")) == NULL) {
printf ("\n...cannot open %s for writing\n", wbuf);
exit (1);
}
gprintf (fpOut, "logging SGL params in file %s\n", wbuf);
}
}
#ifdef DBG_MEM
gmod_logfile (1); /* turn on(1)/off(0) gmod log file */
#endif
/*
* display parameter settings employing global printf function;
* open log file
*/
gprintf (fpOut, "\nthreshold settings:\n");
gprintf (fpOut, " ANGL_THRESH = %f slp_thresh = %f\n",
angl_thresh, tan (angl_thresh * (2.0 * PI / 360.0)));
gprintf (fpOut, " OVLP_THRESH = %f\n", ovlp_thresh);
gprintf (fpOut, " DIST_THRESH = %f\n", d_max);
/*
* memory allocation
*/
if ((inSegm = (struct Segm *) calloc (n_segm, sizeof (struct Segm))) == NULL)
exitmess ("can't allocate mem for struct Segm *inSegm", 1);
if ((sall = (struct linklist *) calloc (n_segm, sizeof (struct linklist))) == NULL)
exitmess ("can't allocate mem for struct linklist *sall", 1);
if ((sgll = (struct linklist *) calloc (n_segm, sizeof (struct linklist))) == NULL)
exitmess ("can't allocate mem for struct linklist *sgll", 1);
/*
* fetch segment data
*/
if (TEST_INPUT == 1) {
printf ("\n...initialize test segments\n");
init_testsegm (inSegm, n_segm);
ymax = HEIGHT;
xmax = WIDTH;
}
else if (INPUT == 1) {
gprintf (fpOut, "input file for segment data: %s\n", buf);
init_segm (file, n_segm, inSegm);
fclose (file);
}
/*
* initialize graphics
*/
ip = ImageAlloc ((long) ymax, (long) xmax, BPS);
#ifdef ECHO_INPUT
printf ("\n...segment data, asread in from file:\n");
for (i = 0; i < n_segm; i++) {
printf ("%4d %3d %3d %3d %3d\n",
(inSegm + i)->segm_ind,
(inSegm + i)->ptO.x, (inSegm + i)->ptO.y,
(inSegm + i)->ptF.x, (inSegm + i)->ptF.y);
}
#endif
printf ("\n...initialize %d empty Segm Adj Lists (SAL)\n", n_segm);
for (i = 0; i < n_segm; i++)
init_sall (sall + i);
#ifdef DEBUG
csall = sall + 0;
printf ("\n...structure parameters for segm adj list number 0:\n");
printf ("sizeof(struct linklist): %d\n", sizeof (struct linklist));
printf (" item length: %d\n", csall->itemlength);
printf (" cur list length: %d\n", csall->listlength);
#endif
printf ("...construct SAL for each of %d segments\n", n_segm);
printf (" (in the form of a doubly linked list of segments)\n");
n_sall = construct_sall (sall, inSegm, n_segm,
angl_thresh, ovlp_thresh, d_max);
/*
* display results
*/
printf ("\n...done with construction of pji-ordered SAL:\n");
if (DISP_MODE == VERBOSE)
for (i = 0; i < n_segm; i++)
show_segm_list (sall + i, i);
else if (DISP_MODE == TERSE)
for (i = 0; i < n_segm; i++)
tshow_segm_list (sall + i, i);
/*
* SGL construction
*/
printf ("\n...initialize %d empty Segm Group Lists (SGL)\n", n_segm);
for (i = 0; i < n_segm; i++)
init_sgll (sgll + i);
#ifdef DEBUG
csgll = sgll + 0;
printf ("\n...structure parameters for segm adj list number 0:\n");
printf (" item length: %d\n", csgll->itemlength);
printf (" cur list length: %d\n", csgll->listlength);
#endif
n_sgl = construct_sgll (inSegm, sall, sgll, n_segm, (double) ovlp_thresh);
/*
* display results
*/
printf ("\n...done with construction of dij-ordered SGL:\n");
gprintf (fpOut, "\tnumber of SGLs: %3d\n", n_sgl);
gprintf (fpOut, "\t ACCEPT_LEVEL: %3d\n", ACCEPT_LEVEL);
gprintf (fpOut, "\t min sz for proc: %3d\n", MIN_SGL_SIZE);
if (DISP_MODE == VERBOSE)
for (i = 0; i < n_segm; i++)
show_segm_list (sgll + i, i);
else if (DISP_MODE == TERSE)
for (i = 0; i < n_segm; i++)
tshow_segm_list (sgll + i, i);
/*
* construct an ordered, cyclic sequence of vertices from the
* endpoints of the segments in a segm group list; handle each
* SGL in turn, skipping those containing less than MIN_SGL_SIZE segments;
*
* there will be n_sgl <= n_sall <= n_segm (closed) polygons, each containing
* nv+1 points: nv thus represents the number of distinct vertices!
*/
#ifdef DEBUG
printf ("\n...size of struct Bdy: %d\n", sizeof (struct Bdy));
#endif
if ((clust_dirn = (float *) calloc (n_segm, sizeof (float))) == NULL)
exitmess ("can't allocate mem for clust_dirn", 1);
if ((clust_area = (int *) calloc (n_segm, sizeof (int))) == NULL)
exitmess ("can't allocate mem for clust_area", 1);
if ((clust_lsz = (int *) calloc (n_segm, sizeof (int))) == NULL)
exitmess ("can't allocate mem for clust_lsz", 1);
if ((hull_area = (int *) calloc (n_segm, sizeof (int))) == NULL)
exitmess ("can't allocate mem for hull_area", 1);
if ((asp_ratio = (float *) calloc (n_segm, sizeof (float))) == NULL)
exitmess ("can't allocate mem for asp_ratio", 1);
min_cluster_area = 10000;
max_cluster_area = 0;
min_asp_ratio = (float) 1000.0;
max_asp_ratio = (float) 0.0;
min_lsz = 1000;
max_lsz = 0;
n_sgl = 0;
for (i = 0; i < n_segm; i++)
*(clust_dirn + i) = (float) 999.0;
for (i = 0; i < n_segm; i++) { /* loop over SGLs */
csgll = sgll + i;
if ((nv = 2 * csgll->listlength) >= 2 * MIN_SGL_SIZE) {
n_sgl++; /* count SGLs of sufficient length */
if ((poly_vert = (struct spoint *) calloc (nv + 1, sizeof (struct spoint))) == NULL)
exitmess ("can't allocate mem for poly_vert", 1);
if ((v_ap = (struct spoint *) calloc (nv + 1, sizeof (struct spoint))) == NULL)
exitmess ("\n...mem allocation for v_ap failed\n", 1);
if ((x_vert = (int *) calloc (nv + 1, sizeof (int))) == NULL)
exitmess ("can't allocate mem for x_vert", 1);
if ((y_vert = (int *) calloc (nv + 1, sizeof (int))) == NULL)
exitmess ("can't allocate mem for y_vert", 1);
/*
* construct polygon (closed array of nv+1 vertices) and
* determine average segment orientation; note that merging
* of segments after SGL construction will result in the elimination
* of segments; for each segment deleted from the SGL, the number of
* vertices must be diminished by two
*/
nvpp = nv + 1;
av_dirn = construct_va (inSegm, csgll, &nvpp, poly_vert);
*(clust_dirn + i) = (float) av_dirn;
nv = nvpp - 1;
/*
* evaluate cluster longitudinal size (no of segments) and aspect ratio,
* a cluster being defined as the set of linear segments in a SGL
*/
*(clust_lsz + i) = nv / 2;
if (*(clust_lsz + i) > max_lsz)
max_lsz = *(clust_lsz + i);
if (*(clust_lsz + i) < min_lsz)
min_lsz = *(clust_lsz + i);
*(asp_ratio + i) = eccentr (inSegm, csgll,
&maxlen, &maxwidth);
if (*(asp_ratio + i) > max_asp_ratio)
max_asp_ratio = *(asp_ratio + i);
if (*(asp_ratio + i) < min_asp_ratio)
min_asp_ratio = *(asp_ratio + i);
/*
* collect cluster areas to be used in histogram evaluation and
* determine minimum and maximum cluster areas
*/
for (iv = 0; iv <= nv; iv++) {
*(x_vert + iv) = (poly_vert + iv)->x;
*(y_vert + iv) = (poly_vert + iv)->y;
}
*(clust_area + i) = zero_moment (nv, x_vert, y_vert);
if (*(clust_area + i) > max_cluster_area)
max_cluster_area = *(clust_area + i);
if (*(clust_area + i) < min_cluster_area)
min_cluster_area = *(clust_area + i);
/*
* display geometrical parameters
*/
#ifdef DEBUG
gprintf (fpOut, "\ngeometr prop of cluster %d:\n", i);
gprintf (fpOut, " no of segments: %d\n",
csgll->listlength);
gprintf (fpOut, " area = %d\n", *(clust_area + i));
gprintf (fpOut, " length = %6.2f, width = %6.2f\n",
maxlen, maxwidth);
gprintf (fpOut, " asp_ratio = %6.2f\n", *(asp_ratio + i));
gprintf (fpOut, " avrg_dirn = %6.2f\n", av_dirn);
#endif
#ifdef SHOW_VERT
printf ("\n...ordered vertex array for SGL<%d>\n", i);
printf (" n_vertex: %d\n", nv);
printf (" avrg slope: %lf\n", av_dirn);
for (iv = 0; iv <= nv; iv++)
printf (" (%d, %d)\n",
(poly_vert + iv)->x, (poly_vert + iv)->y);
#endif
#ifdef SAVE_VERT
gprintf (fpOut, "\n...ordered vertex array for SGL<%d>\n", i);
gprintf (fpOut, " n_vertex: %d\n", nv);
gprintf (fpOut, " avrg slope: %lf\n", av_dirn);
for (iv = 0; iv <= nv; iv++)
gprintf (fpOut, " (%d, %d)\n",
(poly_vert + iv)->x, (poly_vert + iv)->y);
#endif
/*
* construct convex hull of cluster
*/
lnv = (long) nv;
fill_bdy_structure (bdp, poly_vert, lnv, tot_phi);
hullctr = poly_hull_tol (bdp, v_ap, av_dirn, hull_area + i, (float) 0.0, ip, WHITE);
xhullc = hullctr->x;
yhullc = hullctr->y;
/*
* deallocate memory
*/
free (x_vert);
free (y_vert);
free (poly_vert);
free (v_ap);
free (bdp->hpp); /* allocated in poly_approx.c */
free (bdp->ap); /* allocated in poly_approx.c */
free (bdp->v); /* allocated in poly_edge.c */
}
}
if (!n_sgl) {
printf ("No clusters found to process\nExiting!\n");
exit (0);
}
/*
* evaluate SGL (cluster) longitudinal size (no of segments) histogram
*/
nlsz_bins = max_lsz - min_lsz + 1;
if ((lsz_hist = (int *) calloc (nlsz_bins, sizeof (int))) == NULL)
exitmess ("can't allocate mem for lsz_hist", 1);
find_lsz_hist (n_segm, clust_lsz, lsz_hist, nlsz_bins, min_lsz);
tot_number = 0;
gprintf (fpOut, "\nhistogram of cluster longit. sizes:\n");
gprintf (fpOut, " maximum no of segm: %d\n", max_lsz);
gprintf (fpOut, " minimum no of segm: %d\n", min_lsz);
for (ibin = 0; ibin < nlsz_bins; ibin++) {
gprintf (fpOut, " %3d ", *(lsz_hist + ibin));
if ((ibin + 1) % 10 == 0)
gprintf (fpOut, "\n");
tot_number += *(lsz_hist + ibin);
}
gprintf (fpOut, "\n");
/*
* evaluate SGL (cluster) aspect ratio (eccentricity: ex ) histogram
*/
ex_bin_width = (max_asp_ratio - min_asp_ratio) / (float) N_BINS;
if ((ex_hist = (int *) calloc (N_BINS, sizeof (int))) == NULL)
exitmess ("can't allocate mem for ex_hist", 1);
find_ex_hist (n_segm, asp_ratio, ex_hist, ex_bin_width, min_asp_ratio);
tot_number = 0;
gprintf (fpOut, "\nhistogram of cluster aspect ratios:\n");
gprintf (fpOut, " maximum asp ratio: %f\n", max_asp_ratio);
gprintf (fpOut, " minimum asp ratio: %f\n", min_asp_ratio);
gprintf (fpOut, " ex_bin_width: %f\n", ex_bin_width);
for (ibin = 0; ibin < N_BINS; ibin++) {
gprintf (fpOut, " %3d ", *(ex_hist + ibin));
tot_number += *(ex_hist + ibin);
}
gprintf (fpOut, "\n");
/*
* evaluate SGL (cluster) area histogram
*/
area_bin_width = (max_cluster_area - min_cluster_area) / N_BINS;
if ((area_hist = (int *) calloc (N_BINS, sizeof (int))) == NULL)
exitmess ("can't allocate mem for area_hist", 1);
find_area_hist (n_segm, clust_area, area_hist,
area_bin_width, min_cluster_area);
tot_number = 0;
gprintf (fpOut, "\nhistogram of cluster areas:\n");
gprintf (fpOut, " maximum area: %d\n", max_cluster_area);
gprintf (fpOut, " minimum area: %d\n", min_cluster_area);
gprintf (fpOut, " area_bin_width: %d\n", area_bin_width);
for (ibin = 0; ibin < N_BINS; ibin++) {
gprintf (fpOut, " %3d ", *(area_hist + ibin));
tot_number += *(area_hist + ibin);
}
gprintf (fpOut, "\n");
/*
* evaluate nematic order parameter for ensemble of clusters
*/
s_nem = nematic_op (n_sgl, n_segm, clust_dirn);
gprintf (fpOut, "\nnematic order parameter: S = %6.2f\n", s_nem);
free (asp_ratio);
free (ex_hist);
free (clust_area);
free (area_hist);
free (clust_lsz);
free (lsz_hist);
free (clust_dirn);
free (hull_area);
/*
* deallocate memory assigned to lists
*/
printf ("\n...deallocating memory for linked lists\n");
printf (" SALs:\n");
for (i = 0; i < n_segm; i++) {
if ((sall + i)->listlength != 0) {
rm_link = rm_llistlink (sall + i);
#ifdef DBG_MEM
printf (" for SAL<%d>: %d links removed\n",
i, rm_link);
#endif
}
}
printf (" SGLs\n");
for (i = 0; i < n_segm; i++) {
if ((sgll + i)->listlength != 0) {
rm_link = rm_llistlink (sgll + i);
#ifdef DBG_MEM
printf (" for SGL<%d>: %d links removed\n",
i, rm_link);
#endif
}
}
free (inSegm); /* free array of input segments */
free (sall);
free (sgll);
if (WRITE_FILE == 1)
fclose (fpOut);
ImageOut (argv[2], ip);
#ifdef DBG_MEM
printf ("\n...no of bytes still in use: %d\n", gmod_inuse ());
gmod_logfile (0);
#endif
}